home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Online / HBBS / Source / Node / node_serial.c_pre_11aug1997 < prev    next >
Text File  |  1997-08-22  |  11KB  |  449 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5.  
  6. #include <exec/exec.h>
  7. #include <dos/dos.h>
  8.  
  9. #include <devices/serial.h>
  10. #include <hardware/cia.h>
  11.  
  12. #include <clib/exec_protos.h>
  13. #include <clib/alib_protos.h>
  14. #include <clib/dos_protos.h>
  15.  
  16. #define NOTMAIN
  17.  
  18. #define ClrSignal(s)  SetSignal(0,s)
  19.  
  20. #include <hbbs/types.h>
  21. #include <hbbs/defines.h>
  22. #include <hbbs/structures.h>
  23. #include <hbbs/strings.h>
  24. #include <hbbs/errors.h>
  25. #include <hbbs/shared_protos.h>
  26. #include <hbbs/Files.h>
  27.  
  28. #include "Node_Input_protos.h"
  29. #include "Node_Console_protos.h"
  30.  
  31. #include <HBBS/Hbbscommon_protos.h>
  32. #ifdef __SASC
  33. #include <HBBS/hbbscommon_pragmas_sas.h>
  34. #else
  35. #include <HBBS/hbbscommon_pragmas_stc.h>
  36. #endif
  37.  
  38. #include <HBBS/Hbbsnode_protos.h>
  39. #ifdef __SASC
  40. #include <HBBS/Hbbsnode_pragmas_sas.h>
  41. #else
  42. #include <HBBS/Hbbsnode_pragmas_stc.h>
  43. #endif
  44.  
  45. extern struct NodeData *N_ND;
  46. extern struct BBSGlobalData *BBSGlobal;
  47. extern struct Library *HBBSCommonBase;
  48. extern struct Library *HBBSNodeBase;
  49.  
  50. char errstr[2048]; // big enough ?
  51.  
  52. void CleanupSerial( void )
  53. {
  54.   if (!N_ND->NodeDevice.SysopNode)
  55.   {
  56.     if (N_ND->SerBuffer)
  57.     {
  58.       if (N_ND->SerPort)
  59.       {
  60.         if (N_ND->SerWrite)
  61.         {
  62.           if (N_ND->SerOPEN)
  63.           {
  64.             if (N_ND->SerRead)
  65.             {
  66.               AbortSerRead(); // will only abort id request submitted..
  67.               FreeVec(N_ND->SerRead);
  68.             }
  69.             CloseDevice((struct IORequest*)N_ND->SerWrite);
  70.             N_ND->SerOPEN=FALSE;
  71.           }
  72.           DeleteExtIO((struct IORequest*)N_ND->SerWrite);
  73.         }
  74.         DeletePort(N_ND->SerPort);
  75.       }
  76.       FreeVec(N_ND->SerBuffer);
  77.     }
  78.   }
  79.   N_ND->SerOK=FALSE;
  80. }
  81.  
  82. void SerReset( void )
  83. {
  84.   // this routine reads in all waiting data from the serial port and then dumps it!
  85.   UBYTE *mem;
  86.   ULONG bytes;
  87.  
  88.   if (bytes=SerQueryData())
  89.   {
  90.     if (mem=AllocVec(bytes,MEMF_PUBLIC))
  91.     {
  92.       WaitSerReadBlock(mem,bytes); // *C* ooh naughty.. should really have somekind of wait() here..
  93.       FreeVec(mem);
  94.     }
  95.   }
  96. }
  97.  
  98. V_BOOL OpenSerial( void )
  99. {
  100.   N_ND->SerWaiting=FALSE;
  101.   N_ND->SerOK=FALSE;
  102.   N_ND->SerOPEN=FALSE;
  103.   if (!N_ND->NodeDevice.SysopNode)
  104.   {
  105.     if (N_ND->SerBuffer=AllocVec(DEF_SERBUFLEN,MEMF_PUBLIC))
  106.     {
  107.       N_ND->SerBufferLen=DEF_SERBUFLEN;
  108.       if (N_ND->SerPort=CreatePort(0,0))
  109.       {
  110.         if (N_ND->SerWrite = (struct IOExtSer *) CreateExtIO(N_ND->SerPort,(ULONG)sizeof(struct IOExtSer)))
  111.         {
  112.  
  113. /* For Shared Mode XPR
  114.  
  115.           if (N_ND->NodeDevice.NullModemCable)
  116.           {
  117.             N_ND->SerWrite->io_SerFlags       = SERF_SHARED;
  118.           }
  119.           else
  120.           {
  121.             N_ND->SerWrite->io_SerFlags       = SERF_SHARED|SERF_7WIRE|SERF_XDISABLED|SERF_RAD_BOOGIE;
  122.           }
  123. */
  124.           if (!N_ND->NodeDevice.NullModemCable)
  125.           {
  126.             N_ND->SerWrite->io_SerFlags       = SERF_7WIRE|SERF_XDISABLED|SERF_RAD_BOOGIE;
  127.           }
  128.           N_ND->SerWrite->io_RBufLen=16384;
  129.  
  130.           if (!(OpenDevice((STRPTR)N_ND->NodeDevice.SerialDevice,(ULONG)N_ND->NodeDevice.SerialUnit,(struct IORequest *)N_ND->SerWrite,0L) ))
  131.           {
  132.             N_ND->SerOPEN=TRUE;
  133.             // kill data waiting..
  134.             N_ND->SerWrite->IOSer.io_Command  = CMD_RESET;
  135.             DoIO((struct IORequest *)N_ND->SerWrite);
  136.  
  137.  
  138.             // setup port with correct baud rate etc..
  139.             N_ND->SerWrite->IOSer.io_Command  = SDCMD_SETPARAMS;
  140.             N_ND->SerWrite->io_SerFlags       |= SERF_XDISABLED;
  141.             N_ND->SerWrite->io_Baud           = N_ND->NodeDevice.SerialBaud;
  142.             N_ND->SerWrite->io_RBufLen        = 16384; //bytes
  143.             DoIO((struct IORequest *)N_ND->SerWrite);
  144.  
  145.  
  146.             if (N_ND->SerRead = (struct IOExtSer*)AllocVec(sizeof(struct IOExtSer),MEMF_PUBLIC) )
  147.             {
  148.               // duplicate data...
  149.               memcpy(N_ND->SerRead,N_ND->SerWrite,sizeof(struct IOExtSer));
  150.               SerReset();
  151.               N_ND->SerOK=TRUE;
  152.               return(TRUE);
  153.             }
  154.           }
  155.           else HBBS_DoErrorMessage(EMSG_NODEVICE,N_ND->NodeNum,NULL);
  156.         }
  157.       }
  158.     }
  159.     CleanupSerial();
  160.   }
  161.   return(FALSE);
  162. }
  163.  
  164. ULONG ModemGetLine( void )
  165. {
  166.   ULONG ReturnedSigs;
  167.   UBYTE CurrentChar[2]={0,0}; // 2 chars, use ¤tchar for null terminated string type..
  168.   ULONG retval=IN_NOTHING; // this must NOT be returned to the caller!!!!!
  169.  
  170.   struct TimerData *TD;
  171.  
  172.   N_ND->CurrentLine[0]=0; // null terminate the string..
  173.  
  174.   if (TD=SubmitTimer(N_ND->NodeTimer,N_ND->NodeDevice.MaxCommandWait,0))
  175.   {
  176.     do
  177.     {
  178.       if (!N_ND->SerWaiting) SendSerReadData();
  179.  
  180.       // we cant use SetupSigs() and WaitAllSigs() because if we are resetting
  181.       // the modem after a LOGIN_LOCAL sersigs is set to 0... :-)
  182.       // *C* add timeout
  183.       N_ND->SerSig=DEF_SERSIG;
  184.       N_ND->TimerSig=DEF_TIMERSIG;
  185.       ReturnedSigs=Wait(N_ND->SerSig | N_ND->TimerSig);
  186.  
  187.       while (HandleSerSigs(ReturnedSigs) && retval==IN_NOTHING)
  188.       {
  189.         // ok, we got some data from somehwere...
  190.  
  191.         CurrentChar[0]=N_ND->IBuffer[0];
  192.  
  193.         if (CurrentChar[0]>=0x20 && CurrentChar[0]!=127) // i.e. not unprintable or a control char..
  194.         {
  195.           strcat(N_ND->CurrentLine,CurrentChar);
  196.         }
  197.         else
  198.         {
  199.           if (CurrentChar[0]=='\n')
  200.           {
  201.             if (strlen(N_ND->CurrentLine)>0) retval=IN_GOTLINE;
  202.           }
  203.         }
  204.       }
  205.  
  206.       if ((retval==IN_NOTHING) && (CheckTimer(N_ND->NodeTimer,TD)))
  207.       {
  208.         TD=NULL;
  209.         retval=IN_TIMEOUT;
  210.       }
  211.     }
  212.     while (retval==IN_NOTHING);
  213.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  214.  
  215.     if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
  216.     {
  217.       ConWriteStr(N_ND->CurrentLine);
  218.       ConWriteStr(str_CRLF);
  219.     }
  220.     if (N_ND->SerWaiting) AbortSerRead();
  221.   }
  222.   return(retval);
  223. }
  224.  
  225. void ModemError(char *command, char *result)
  226. {
  227.   if (N_ND->NodeDevice.ModemLog)
  228.   {
  229.     sprintf(errstr,"When Sending the command \"%s\" the modem returned \"%s\"",command,result);
  230.  
  231.     HBBS_LogError(N_ND->NodeSettings.ModemLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  232.   }
  233. }
  234.  
  235. void TurnEchoOn( void )
  236. {
  237.   struct Node *node;
  238.   short retriesleft;
  239.   BOOL Done;
  240.   ULONG result;
  241.  
  242.  
  243.   PutText("\033[37;0m\n");
  244.   for (node=N_ND->NodeDevice.TurnOnEcho->lh_Head;node->ln_Succ;node=node->ln_Succ)
  245.   {
  246.     if (node->ln_Name)
  247.     {
  248.       Done=FALSE;
  249.       retriesleft=N_ND->NodeDevice.EchoRetries;
  250.       do
  251.       {
  252.         if (retriesleft!=N_ND->NodeDevice.EchoRetries)
  253.         {
  254.           ConWriteStr("Retrying Modem...\n\r");
  255.         }
  256.  
  257.         retriesleft--;
  258.         Delay(N_ND->NodeDevice.TurnOnEchoDelay);
  259.         SerReset();
  260.         SerWriteStr(node->ln_Name);
  261.         SerWriteStr(str_CRLF);
  262.         if (result=ModemGetLine()==IN_GOTLINE)
  263.         {
  264.           // ok, got some input..
  265.  
  266.           if (stricmp(node->ln_Name,N_ND->CurrentLine)==0)
  267.           {  // echo is already on, so discard this line and read another line..
  268.             result=ModemGetLine();
  269.           }
  270.           if (result==IN_GOTLINE)
  271.           {
  272.             if (stricmp("OK",N_ND->CurrentLine)==0) Done=TRUE;
  273.           }
  274.         }
  275.       } while (!Done && retriesleft>0);
  276.     }
  277.   }
  278.   SerReset();
  279. }
  280.  
  281. V_BOOL SendModemString(char *str)
  282. {
  283.   ULONG err=1;
  284.   ULONG loop,loop2;
  285.   BOOL linemismatch;
  286.  
  287.   char *cvtstr;
  288.  
  289.   if (cvtstr=DupStr(str))
  290.   {
  291.  
  292.     // remove the '~'s fromt the string so that we can compare the returned string from the modem
  293.     // (the modem won't return the '~'s because it'll never get them!
  294.  
  295.     loop=0,loop2=0;
  296.     while (str[loop])
  297.     {
  298.       if (str[loop]!='~')
  299.       {
  300.         cvtstr[loop2]=str[loop];
  301.       }
  302.       loop2++;
  303.       loop++;
  304.     }
  305.     cvtstr[loop2]=0;
  306.  
  307.     loop2=N_ND->NodeDevice.CommandRetries;
  308.  
  309.     do
  310.     {
  311.  
  312.       // this loop sends the command to the modem and wait for the characters to
  313.       // be echoed back.  if we don't get back what we send we try it again!
  314.  
  315.       loop=N_ND->NodeDevice.CommandRetries;
  316.       do
  317.       {
  318.         Delay(N_ND->NodeDevice.DelayBetweenCmds);
  319.         SerReset(); //clear all crap before we send our new string..
  320.         SerDelayWriteStr(str); // send the command to the modem
  321.         SerWriteStr(str_CRLF); // and a cr+lf
  322.         ModemGetLine(); // then check the modem echo'd the chars we sent it.
  323.         if (linemismatch=(stricmp(cvtstr,N_ND->CurrentLine)!=0 ? TRUE : FALSE)) // compare with cvtstr and not str..
  324.         {
  325.           // modem did not retunr the same string we sent it, the modem's local echo must be off so turn it on
  326.           TurnEchoOn();
  327.         }
  328.       } while (loop-- && linemismatch); // if we had a line mismatch then retry sending the command now that echo is on.
  329.  
  330.       // now wait the modem's responce from the command we sent it.
  331.  
  332.       // right if we are here then we know we're gonna get a blank line and a timeout
  333.       // or OK OR ERROR..  if we don't get OK then we retry the command...
  334.       ModemGetLine();
  335.  
  336.     } while (loop2-- && stricmp(N_ND->CurrentLine,"OK")!=0 && (err=stricmp(N_ND->CurrentLine,"ERROR"))==0);
  337.     if (!err) ModemError(str,N_ND->CurrentLine);
  338.  
  339.     FreeStr(cvtstr);
  340.   }
  341.   return(err);
  342. }
  343.  
  344. void OffHook( void )
  345. {
  346.   if (N_ND->NodeSettings.UseDevice)
  347.   {
  348.     SendModemString(N_ND->NodeDevice.OffHookString);
  349.   }
  350. }
  351.  
  352. void ReOpenSerial( void )
  353. {
  354.  
  355.   // closing and opening the serial port has the effect of dropping dtr,
  356.   // forcing a hangup of the modem.
  357.  
  358.   V_SMALLNUM loop=N_ND->NodeDevice.ReOpenRetries;
  359.   if (!N_ND->NodeDevice.SysopNode)
  360.   {
  361.     CleanupSerial();
  362.  
  363.     while (loop-- && N_ND->SerOK==FALSE)
  364.     {
  365.       Delay(N_ND->NodeDevice.ReOpenDelay);
  366.       OpenSerial();
  367.     }
  368.  
  369.     if (!N_ND->SerOK)
  370.     {
  371.       HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,ESTR_NOSERIAL,TYPE_CRITICAL);
  372.     }
  373.   }
  374. }
  375.  
  376. void SendHangupCommands( void )
  377. {
  378.   struct Node *node;
  379.  
  380.   for (node=N_ND->NodeDevice.CommandModeString->lh_Head;node->ln_Succ;node=node->ln_Succ)
  381.   {
  382.     if (node->ln_Name) SerDelayWriteStr(node->ln_Name);
  383.   }
  384.   SendModemString(N_ND->NodeDevice.HangUpString);
  385. }
  386.  
  387. void HangUp( void )
  388. {
  389.  
  390.   if (N_ND->NodeSettings.UseDevice)
  391.   {
  392.     if (!N_ND->NodeDevice.NullModemCable)
  393.     {
  394.       if (!N_ND->NodeDevice.DropDTRHangup)
  395.       {
  396.         SendHangupCommands();
  397.       }
  398.       ReOpenSerial();
  399.       if (CarrierLost())
  400.       {
  401.         if (N_ND->ConOK) ConWriteStr("Hungup OK.\r\n");
  402.       }
  403.       else
  404.       {
  405.         sprintf(errstr,"Could not hangup using DTR.");
  406.         HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  407.         SendHangupCommands();
  408.  
  409.         if (!CarrierLost())
  410.         {
  411.           sprintf(errstr,"Could not hangup using hangup commands either.");
  412.           HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  413.         }
  414.  
  415.       }
  416.       OffHook();
  417.     }
  418.     else
  419.     {
  420.       ReOpenSerial();
  421.     }
  422.   }
  423. }
  424.  
  425. V_BOOL InitModem( void )
  426. {
  427.   struct Node *node;
  428.  
  429.   if (N_ND->NodeSettings.UseDevice)
  430.   {
  431.     if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
  432.     {
  433.       ConWriteStr("Initialising Modem...\n\r");
  434.     }
  435.  
  436.     TurnEchoOn();
  437.     Delay(N_ND->NodeDevice.DelayBetweenCmds);
  438.     for (node=N_ND->NodeDevice.ModemInit->lh_Head;node->ln_Succ;node=node->ln_Succ)
  439.     {
  440.       if (node->ln_Name) SendModemString(node->ln_Name);
  441.     }
  442.     // wait a bit nd dump any data.
  443.     Delay(N_ND->NodeDevice.DelayBetweenCmds);
  444.     SerReset();
  445.   }
  446.   return(TRUE);
  447. }
  448.  
  449.